home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
editors
/
mjovesrc.zoo
/
disp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-04
|
30KB
|
1,493 lines
/***************************************************************************
* This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
* is provided to you without charge, and with no warranty. You may give *
* away copies of JOVE, including sources, provided that this notice is *
* included in all the files. *
***************************************************************************/
#include "jove.h"
#include "ctype.h"
#include "termcap.h"
#include "chars.h"
#include "fp.h"
#include "disp.h"
#ifdef IPROCS
# include "iproc.h"
#endif
#ifdef MAC
# include "mac.h"
#else
# ifdef STDARGS
# include <stdarg.h>
# else
# include <varargs.h>
# endif
# include <sys/stat.h>
#endif
#include <signal.h>
private void
#ifdef ID_CHAR
DeTab proto((int, char *, char *, size_t, int)),
DelChar proto((int, int, int)),
InsChar proto((int, int, int, char *)),
#endif
DoIDline proto((int)),
do_cl_eol proto((int)),
ModeLine proto((Window *)),
GotoDot proto((void)),
UpdLine proto((int)),
UpdWindow proto((Window *, int));
#ifdef MSDOS
extern void dobell proto((int x));
#else
private void dobell proto((int x));
#endif
#ifdef ID_CHAR
private bool
IDchar proto ((char *, int, int)),
OkayDelete proto ((int, int, int)),
OkayInsert proto ((int, int));
private int
NumSimilar proto ((char *, char *, int)),
IDcomp proto ((char *, char *, int));
#endif
private int
AddLines proto((int, int)),
DelLines proto((int, int));
int DisabledRedisplay = NO;
/* Kludge windows gets called by the routines that delete lines from the
buffer. If the w->w_line or w->w_top are deleted and this procedure
is not called, the redisplay routine will barf. */
void
ChkWindows(line1, line2)
Line *line1,
*line2;
{
register Window *w = fwind;
register Line *lp,
*lend = line2->l_next;
do {
if (w->w_bufp == curbuf) {
for (lp = line1->l_next; lp != lend; lp = lp->l_next) {
if (lp == w->w_top)
w->w_flags |= W_TOPGONE;
if (lp == w->w_line)
w->w_flags |= W_CURGONE;
}
}
w = w->w_next;
} while (w != fwind);
}
/* Deleted and killed Lines are about to be recycled: check for dangling refs */
void
ChkWinLines()
{
register Window *w = fwind;
do {
if (w->w_top == NULL || w->w_top->l_dline == NULL_DADDR)
w->w_flags |= W_TOPGONE;
if (w->w_line == NULL || w->w_line->l_dline == NULL_DADDR)
w->w_flags |= W_CURGONE;
w = w->w_next;
} while (w != fwind);
}
private bool RingBell; /* So if we have a lot of errors ...
ring the bell only ONCE */
void
redisplay()
{
register Window *w = fwind;
int lineno,
done_ID = NO,
i;
register struct scrimage *des_p,
*phys_p;
if (DisabledRedisplay == YES)
return;
curwind->w_line = curwind->w_bufp->b_dot;
curwind->w_char = curwind->w_bufp->b_char;
#ifdef MAC
InputPending = NO;
#else
if ((InputPending = charp()) != NO) /* calls CheckEvent, which could */
return; /* result in a call to rediplay(). We don't want that. */
#endif
#ifdef BSD_SIGS
if (UpdFreq)
SigHold(SIGALRM);
#endif
if (RingBell) {
dobell(1);
RingBell = NO;
}
AbortCnt = BufSize; /* initialize this now */
if (UpdMesg)
DrawMesg(YES);
for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {
UpdWindow(w, lineno);
lineno += w->w_height;
}
UpdModLine = NO;/* Now that we've called update window, we can
assume that the modeline will be updated. But
if while redrawing the modeline the user types
a character, ModeLine() is free to set this on
again so that the modeline will be fully drawn
at the next redisplay. */
des_p = DesiredScreen;
phys_p = PhysScreen;
for (i = 0; i < ILI; i++, des_p++, phys_p++) {
if (!done_ID && (des_p->s_id != phys_p->s_id)) {
DoIDline(i);
done_ID = YES;
}
if ((des_p->s_flags & (DIRTY | L_MOD)) ||
(des_p->s_id != phys_p->s_id) ||
(des_p->s_vln != phys_p->s_vln) ||
(des_p->s_offset != phys_p->s_offset))
UpdLine(i);
if (InputPending)
goto ret;
}
if (Asking) {
Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, AskingWidth)));
/* Nice kludge */
flushscreen();
} else {
GotoDot();
}
ret:
; /* yuck */
#ifdef BSD_SIGS
if (UpdFreq)
SigRelse(SIGALRM);
#endif
#ifdef MAC
if (Windchange)
docontrols();
#endif /* MAC */
}
#ifndef IBMPC
private void
dobell(n)
int n;
{
while (--n >= 0) {
#ifndef MAC
if (VisBell && VB)
putstr(VB);
else
putpad(BL, 1);
#else
SysBeep(5);
#endif
}
flushscreen();
}
#endif /* IBMPC */
/* find_pos() returns the position on the line, that C_CHAR represents
in LINE */
private int
find_pos(line, c_char)
Line *line;
int c_char;
{
return calc_pos(lcontents(line), c_char);
}
int
calc_pos(lp, c_char)
register char *lp;
register int c_char;
{
register int pos = 0;
register int c;
while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) {
if (c == '\t')
pos += (tabstop - (pos % tabstop));
else if (jiscntrl(c))
pos += 2;
else
pos += 1;
}
return pos;
}
bool UpdModLine = NO,
UpdMesg = NO;
private void
DoIDline(start)
int start;
{
register struct scrimage *des_p = &DesiredScreen[start];
struct scrimage *phys_p = &PhysScreen[start];
register int i,
j;
/* Some changes have been made. Try for insert or delete lines.
If either case has happened, Addlines and/or DelLines will do
necessary scrolling, also CONVERTING PhysScreen to account for the
physical changes. The comparison continues from where the
insertion/deletion takes place; this doesn't happen very often,
usually it happens with more than one window with the same
buffer. */
if (!CanScroll)
return; /* We should never have been called! */
for (i = start; i < ILI; i++, des_p++, phys_p++)
if (des_p->s_id != phys_p->s_id)
break;
for (; i < ILI; i++) {
for (j = i + 1; j < ILI; j++) {
des_p = &DesiredScreen[j];
phys_p = &PhysScreen[j];
if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)
break;
if (des_p->s_id == PhysScreen[i].s_id) {
if (des_p->s_id == 0)
continue;
if (AddLines(i, j - i)) {
DoIDline(j);
return;
}
break;
}
if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {
if (des_p->s_id == 0)
continue;
if (DelLines(i, j - i)) {
DoIDline(i);
return;
}
break;
}
}
}
}
/* Make DesiredScreen reflect what the screen should look like when we are done
with the redisplay. This deals with horizontal scrolling. Also makes
sure the current line of the Window is in the window. */
bool ScrollAll = NO;
private void
UpdWindow(w, start)
register Window *w;
int start;
{
Line *lp;
int i,
upper, /* top of window */
lower, /* bottom of window */
strt_col, /* starting print column of current line */
ntries = 0; /* # of tries at updating window */
register struct scrimage *des_p,
*phys_p;
Buffer *bp = w->w_bufp;
retry:
if (w->w_flags & W_CURGONE) {
w->w_line = bp->b_dot;
w->w_char = bp->b_char;
}
if (w->w_flags & W_TOPGONE)
CentWind(w); /* reset topline of screen */
w->w_flags &= ~(W_CURGONE | W_TOPGONE);
/* make sure that the current line is in the window */
upper = start;
lower = upper + w->w_height - 1; /* don't include modeline */
for (i = upper, lp = w->w_top; i < lower && lp != NULL; lp = lp->l_next, i++)
if (lp == w->w_line)
break;
if (i == lower || lp == NULL) {
ntries += 1;
if (ntries == 1) {
CalcWind(w);
goto retry;
} else if (ntries == 2) {
w->w_top = w->w_line = w->w_bufp->b_first;
writef("\rERROR in redisplay: I got hopelessly lost!");
dobell(2);
goto retry;
} else if (ntries == 3) {
writef("\n\rOops, still lost, quitting ...\r\n");
finish(SIGHUP);
}
}
/* first do some calculations for the current line */
{
int diff = (w->w_flags & W_NUMLINES) ? 8 : 0,
end_col;
strt_col = ScrollAll? w->w_LRscroll : PhysScreen[i].s_offset;
end_col = strt_col + (CO - 2) - diff;
/* Right now we are displaying from strt_col to
end_col of the buffer line. These are PRINT
columns, not actual characters. */
w->w_dotcol = find_pos(w->w_line, w->w_char);
/* if the new dotcol is out of range, res